package com.sangeng.entity;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sangeng.mapper.Exception.SystemException;
import com.sangeng.config.RedisCache;
import com.sangeng.enums.AppHttpCodeEnum;
import com.sangeng.mapper.LoginUserMapper;
import com.sangeng.service.LoginUserService;
import com.sangeng.util.BeanCopyUtils;
import com.sangeng.util.JwtUtil;
import com.sangeng.vo.BlogUserLoginVo;
import com.sangeng.vo.UserInfoVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Objects;

/**
 * 用户表(User)表服务实现类
 *
 * @author makejava
 * @since 2022-08-19 17:34:36
 */
@Service
public class LoginUserServiceImpl extends ServiceImpl<LoginUserMapper, User> implements LoginUserService {
    @Autowired
   RedisCache redisCache;
    @Autowired
    //用于验证
    AuthenticationManager authenticationManager;
    @Autowired
    PasswordEncoder passwordEncoder;

    @Override
   public ResponseResult login(User user){


       //调用authenticationManager的authenticate()方法用于验证
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserName(),user.getPassword());
     //这里会返回LoginUser的信息
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
       if(Objects.isNull(authenticate)){
           new RuntimeException("用户名或密码错误");
       }
       //如果执行到这说明登录成功
       //获取userid，用于生成jwt，jwt的生成使用工具类
       LoginUserDetailsImpl loginUser = (LoginUserDetailsImpl)authenticate.getPrincipal();
       String userId = loginUser.getUser().getId().toString();
       String jwt = JwtUtil.createJWT(userId);
       //将loginUser的信息存入redis中，后面根据key去取出用户的详细信息，比如权限等
       redisCache.setCacheObject("bloglogin:"+userId,loginUser);
       UserInfoVo userInfoVo = BeanCopyUtils.copyBean(loginUser, UserInfoVo.class);
       BlogUserLoginVo blogUserLoginVo = new BlogUserLoginVo(jwt, userInfoVo);
        return  ResponseResult.okResult(blogUserLoginVo);

   }

    @Override
    public ResponseResult logOut() {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUserDetailsImpl loginUser = (LoginUserDetailsImpl)authentication.getPrincipal();
        String userId = loginUser.getUser().getId().toString();
        redisCache.deleteObject("bloglogin:"+userId);
        return ResponseResult.okResult();

    }

    @Override
    public ResponseResult registerUser(User user) {
//优化使用validationApi
        //验证字段不为空
        if(!StringUtils.hasText(user.getUserName())){
            throw  new SystemException(AppHttpCodeEnum.USERNAME_NOT_NULL);
        }
        if(!StringUtils.hasText(user.getPassword())){
            throw new SystemException(AppHttpCodeEnum.PASSWORD_NOT_NULL);
        }
        if(!StringUtils.hasText(user.getEmail())){
            throw new SystemException(AppHttpCodeEnum.EMAIL_NOT_NULL);
        }
        if(!StringUtils.hasText(user.getNickName())){
            throw new SystemException(AppHttpCodeEnum.NICKNAME_NOT_NULL);
        }
        //对数据进行是否存在的判断
        if(userNameExist(user.getUserName())){
            throw new SystemException(AppHttpCodeEnum.USERNAME_EXIST);
        }
        if(nickNameExist(user.getNickName())){
            throw new SystemException(AppHttpCodeEnum.NICKNAME_EXIST);
        }
         //对密码进行加密处理,加密这个类已经注入bean容器了
        String password = passwordEncoder.encode(user.getPassword());
        user.setPassword(password);
        save(user);
  return ResponseResult.okResult();
    }

    private boolean nickNameExist(String nickName) {
        LambdaQueryWrapper<User> userQueryWrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<User> eq = userQueryWrapper.eq(User::getNickName, nickName);

        //大于0表示数据库中已存在该昵称
        return count(eq)>0;
    }

    private boolean userNameExist(String userName) {
        LambdaQueryWrapper<User> userQueryWrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<User> eq = userQueryWrapper.eq(User::getUserName, userName);
        //大于0表示数据库中已存在该用户名
        return count(eq)>0;
    }
}

